package com.heiko.myopenglrecord2

import android.content.Context
import android.opengl.GLES20
import com.heiko.myopenglrecord2.utils.OpenGLUtils
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import kotlin.properties.Delegates

abstract class AbstractFilter(context: Context, vertexShaderId: Int, fragmentShaderId: Int) {
    private var vTexture by Delegates.notNull<Int>()
    private var vCoord by Delegates.notNull<Int>()
    private var vPosition by Delegates.notNull<Int>()
    private var width by Delegates.notNull<Int>()
    private var height by Delegates.notNull<Int>()
    protected var program: Int
    private var VERTEX = floatArrayOf(
        -1.0f, -1.0f,
        1.0f, -1.0f,
        -1.0f, 1.0f,
        1.0f, 1.0f
    )

    private var TEXTURE = floatArrayOf(
        0.0f, 0.0f,
        1.0f, 0.0f,
        0.0f, 1.0f,
        1.0f, 1.0f
    )

    private lateinit var vertexBuffer: FloatBuffer //顶点坐标缓存区
    private lateinit var textureBuffer: FloatBuffer // 纹理坐标

    init {
        val vertexShader: String = OpenGLUtils.readRawTextFile(context, vertexShaderId)
        val fragShader: String = OpenGLUtils.readRawTextFile(context, fragmentShaderId)

        program = OpenGLUtils.loadProgram(vertexShader, fragShader)

        onFilterCreate()
    }

    protected open fun onFilterCreate() {
        vPosition = GLES20.glGetAttribLocation(program, "vPosition")
        vCoord = GLES20.glGetAttribLocation(program, "vCoord")
        vTexture = GLES20.glGetUniformLocation(program, "vTexture")

        vertexBuffer = ByteBuffer.allocateDirect(4 * 4 * 2)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer()
        vertexBuffer.clear()
        vertexBuffer.put(VERTEX)

        textureBuffer = ByteBuffer.allocateDirect(4 * 4 * 2)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer()
        textureBuffer.clear()
        textureBuffer.put(TEXTURE)
    }

    fun setSize(width: Int, height: Int) {
        this.width = width
        this.height = height
    }

    open fun onDraw(texture: Int): Int {
        //告诉GPU，宽和高，做好准备
        GLES20.glViewport(0, 0, width, height)
        //使用程序
        GLES20.glUseProgram(program)

        //传递vertexBuffer到vPosition
        vertexBuffer.position(0)
        GLES20.glVertexAttribPointer(
            vPosition, 2, GLES20.GL_FLOAT,
            false, 0, vertexBuffer
        )
        GLES20.glEnableVertexAttribArray(vPosition)

        //传递textureBuffer到vCoord
        textureBuffer.position(0)
        GLES20.glVertexAttribPointer(
            vCoord, 2, GLES20.GL_FLOAT,
            false, 0, textureBuffer
        )
        GLES20.glEnableVertexAttribArray(vCoord)

        //激活一个图层
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
        //绑定一个采样器 (将textures上的像素数据放到图层上，并绑定采样器)
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture)
        //传值，传给片元程序的变量，不需要ByteBuffer，内部已经集成好了
        //告诉GPU，摄像头采集的数据，现在是在哪个图层
        GLES20.glUniform1i(vTexture, 0)

        beforeDraw()

        //真正开始渲染
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)
        return texture
    }

    open fun beforeDraw() {}
}